use std::collections::HashMap;

use crate::{
    components::{json_val_to_string, ButtonProp, DataEditInner, EditColumn, EditRowState},
    report::sub_report::SubHeaderSignal,
};
use icondata as i;
use leptos::prelude::*;
use leptos_icons::*;
use serde_json::Value;
use shq_common::prelude::{
    report::ReportDefine, AndOr, ColumnCell, FliterItem, Operator, WhereCause,
};
use shq_web_controls::{SelectOption, SelectRaw, TableState};
use thaw_utils::ArcOneCallback;
#[component]
pub fn ReportHeader(
    #[prop(optional, into)] title: MaybeProp<String>,
    rept_define: Signal<ReportDefine>,
    #[prop(optional, into)] param_vals: RwSignal<Vec<(String, String)>>,
    #[prop(optional, into)] group_index: RwSignal<u8>,
    #[prop(optional, into)] hidden: bool,
    #[prop(optional, into)] options_map: MaybeProp<HashMap<String, Vec<String>>>,
) -> impl IntoView {
    let table_state =
        use_context::<ReadSignal<TableState>>().expect("ReadSignal<TableState>在上下文中不存在");
    let sub_header_signal = use_context::<StoredValue<SubHeaderSignal>>();
    let unit_name = StoredValue::new(rept_define.with_untracked(|rd| rd.unit.to_string()));
    let is_sub = sub_header_signal.is_some();
    let title = Memo::new(move |_| {
        let title = if let Some(t) = title.get() {
            t
        } else {
            rept_define.with_untracked(|rd| rd.title.clone())
        };
        if is_sub {
            format!("{}({})", title, unit_name.get_value())
        } else {
            title
        }
    });
    let field_props = Memo::new(move |_| {
        let opts_map = options_map.get();
        rept_define.with_untracked(|rd| {
            let mut cols = if !is_sub {
                rd.params
                    .iter()
                    .filter(|p| p.grid > 0)
                    .map(|p| p.clone().into())
                    .collect::<Vec<EditColumn>>()
            } else {
                vec![]
            };
            for c in rd.columns.iter() {
                if let ColumnCell::Leaf(col) = c {
                    if let Some(ps) = col.param_selected.as_ref() {
                        let opts = opts_map
                            .as_ref()
                            .map(|oms| {
                                oms.get(&col.name)
                                    .expect(&format!("列{}的选项数据未找到", col.name))
                            })
                            .expect("param_selected获取选项数据失败");
                        let default_value = table_state.with_untracked(|ts| {
                            ts.filter(&col.name)
                                .map(|f| {
                                    f.with(|wc| {
                                        wc.as_ref().map(|wc| wc.filter_items[0].value.clone())
                                    })
                                })
                                .flatten()
                                .flatten()
                        });
                        cols.push(EditColumn::from_param_selected(
                            &col.name,
                            col.title.as_ref().map(|s| s.as_str()).unwrap_or(""),
                            ps.multiple,
                            opts.clone(),
                            default_value,
                            ps.grid,
                        ));
                    }
                }
            }
            cols
        })
    });
    let group_view = move || {
        rept_define.with_untracked(|rd| {
            if rd.groups.len() == 0 {
                return None;
            } else {
                let options = rd
                    .groups
                    .iter()
                    .enumerate()
                    .map(|(i, g)| SelectOption {
                        label: g.title.clone(),
                        value: i as u8,
                    })
                    .collect::<Vec<SelectOption<u8>>>();
                let label = rd
                    .groups
                    .get(group_index.get() as usize)
                    .map(|g| g.title.clone())
                    .unwrap_or("".to_owned());
                let label = format!("层级:{}", label);
                let on_select = ArcOneCallback::new(move |val: Option<u8>| {
                    group_index.set(val.unwrap_or(0));
                });
                Some(view! {
                    <SelectRaw values=vec![group_index.get()]
                            options
                            on_select
                    >
                            <div class="btn btn-sm" style="width:120px">{label}</div>
                    </SelectRaw>
                })
            }
        })
    };
    let params_edit = move || {
        if field_props.with(|cols| cols.is_empty()) {
            return None;
        }
        let button_props = vec![ButtonProp::new(
            "生成".to_string(),
            i::AiSaveOutlined,
            ArcOneCallback::new(move |vals: Vec<(String, Value)>| {
                for (k, v) in vals.into_iter() {
                    let is_param =
                        param_vals.with_untracked(|vals| vals.iter().any(|(pk, _)| pk == &k));
                    let sval = json_val_to_string(&v);
                    if is_param {
                        param_vals.update(|params| {
                            if let Some((_, pv)) = params.iter_mut().find(|(pk, _)| pk == &k) {
                                if pv != &sval {
                                    *pv = sval;
                                }
                            } else {
                                params.push((k, sval));
                            }
                        });
                    } else {
                        let wc = table_state.with_untracked(|ts| ts.filter(&k).unwrap());
                        wc.update(|wc| {
                            let op = if sval.contains("|") {
                                Operator::In
                            } else {
                                Operator::Eq
                            };
                            let fi = FliterItem {
                                operator: op,
                                value: Some(sval.clone()),
                            };
                            *wc = Some(WhereCause {
                                field_name: k.clone(),
                                filter_items: vec![fi],
                                and_or: AndOr::And,
                            });
                        });
                    }
                }
            }),
        )];
        let (edit_row_data, _) = signal(
            field_props.with(|cols| EditRowState::from_columns(&cols, param_vals.get_untracked())),
        );
        Some(view! {
            <DataEditInner field_props edit_row_data button_props/>
        })
    };
    if !hidden {
        Some(view! {
            <div class="flex-none navbar bg-base-100 rounded-t-lg">
                <div class="navbar-start">
                    <a class="btn btn-ghost normal-case text-base">{title.get_untracked()}</a>
                </div>
                <div class="navbar-center">
                    {params_edit}
                </div>
                {if let Some(shs) = sub_header_signal {
                    let maximize_sub_window= shs.with_value(|s| s.maximize_sub_window);
                    let context_action_index= shs.with_value(|s| s.context_action_index);
                    let icon = Signal::derive(move || {
                        if !maximize_sub_window.get() {
                            i::VsWindow
                        } else {
                            i::VsMultipleWindows
                        }
                    });
                    view! {
                        <div class="navbar-end flex gap-4">
                            <button type="button" on:click=move |_| {maximize_sub_window.set(!maximize_sub_window.get_untracked());}>
                                <Icon icon width="20px" height="20px"/>
                            </button>
                            <button type="button" on:click=move |_| {context_action_index.set(None); maximize_sub_window.set(false);}>
                                <Icon icon=i::MdiWindowClose width="20px" height="20px"/>
                            </button>
                        </div>
                    }.into_any()
                } else {
                    view!{
                        <div class="navbar-end flex gap-4">
                            {group_view}
                            <a class="btn btn-ghost normal-case text-base">单位:{unit_name.get_value()}</a>
                        </div>
                    }.into_any()
                }}
            </div>
        })
    } else {
        None
    }
}
